import React, { useState, useEffect } from 'react';
import { Row, Col, Tooltip } from 'antd';
import { IconFontTool } from 'src/components/IconFont';
import undoManager from '../utils/undoManager';
import { IS_ALIGNMENT_TRUE, IS_ALIGNMENT_FALSE, ADD_UNDO_MANAGER, eventEmitter } from '../utils/event';
import './toolbar.less';

export default function ToolBar({ _graph, _graphWrap, disabled }) {
  const [mode, setMode] = useState('default');
  const [hasUndo, setHasUndo] = useState(false); // 是否有撤销
  const [hasRedo, setHasRedo] = useState(false); // 是否有恢复
  const [isAlignOk, setIsAlignOk] = useState(false); // 是否可以对其的状态

  useEffect(() => {
    undoManager.setCallback(checkUndoManagerState);
    undoManager.setLimit(10);
  }, []);

  useEffect(() => {
    eventEmitter.on(IS_ALIGNMENT_TRUE, () => {
      setIsAlignOk(true);
    });
    eventEmitter.on(IS_ALIGNMENT_FALSE, () => {
      setIsAlignOk(false);
    });
    eventEmitter.on(ADD_UNDO_MANAGER, ({ undo, redo }) => {
      undoManager.add({
        undo: undo,
        redo: redo,
      });
    });
  }, []);

  // 设置模式，目前有default、dragCanvas两种
  function setFlowMode(mode) {
    setMode(mode);
    _graph.current.setMode(mode);
    if (mode === 'dragCanvas') {
      _graphWrap.current.className = 'cursor-move';
    } else {
      _graphWrap.current.className = 'cursor-default';
    }
    if (_graph.current._edgeMenu) {
      _graph.current._edgeMenu.style.display = 'none';
    }
    if (_graph.current._nodeMenu) {
      _graph.current._nodeMenu.style.display = 'none';
    }
  }

  // alignRedo 对齐
  function alignRedo(direction) {
    if (!isAlignOk) {
      return;
    }
    const nodes = _graph.current.findAllByState('node', 'selected');
    switch (direction) {
      case 'left':
        const left = nodes.reduce((left, node, i) => {
          const x = node.getModel().x;
          left = i === 0 ? x : left > x ? x : left;
          return left;
        }, 0);
        nodes.forEach((node) => {
          const model = node.getModel();
          model.x = left;
        });
        break;

      case 'right':
        const right = nodes.reduce((right, node, i) => {
          const x = node.getModel().x;
          const { width } = node._cfg.keyShape && node._cfg.keyShape._attrs;
          right = i === 0 ? x + width : right < x + width ? x + width : right;
          return right;
        }, 0);
        nodes.forEach((node) => {
          const model = node.getModel();
          const { width } = node._cfg.keyShape && node._cfg.keyShape._attrs;
          model.x = right - width;
        });
        break;

      case 'center':
        const center = nodes.reduce((center, node, i) => {
          const x = node.getModel().x;
          const { width } = node._cfg.keyShape && node._cfg.keyShape._attrs;
          center = i === 0 ? x + width / 2 : (center + x + width / 2) / 2;
          return center;
        }, 0);
        nodes.forEach((node) => {
          const model = node.getModel();
          const { width } = node._cfg.keyShape && node._cfg.keyShape._attrs;
          model.x = center - width / 2;
        });
        break;

      case 'top':
        const top = nodes.reduce((top, node, i) => {
          const y = node.getModel().y;
          top = i === 0 ? y : top > y ? y : top;
          return top;
        }, 0);
        nodes.forEach((node) => {
          const model = node.getModel();
          model.y = top;
        });
        break;

      case 'bottom':
        const bottom = nodes.reduce((bottom, node, i) => {
          const y = node.getModel().y;
          const { height } = node._cfg.keyShape && node._cfg.keyShape._attrs;
          bottom = i === 0 ? y + height : bottom < y + height ? y + height : bottom;
          return bottom;
        }, 0);
        nodes.forEach((node) => {
          const model = node.getModel();
          const { height } = node._cfg.keyShape && node._cfg.keyShape._attrs;
          model.y = bottom - height;
        });
        break;

      case 'middle':
        const middle = nodes.reduce((middle, node, i) => {
          const y = node.getModel().y;
          const { height } = node._cfg.keyShape && node._cfg.keyShape._attrs;
          middle = i === 0 ? y + height / 2 : (middle + y + height / 2) / 2;
          return middle;
        }, 0);
        nodes.forEach((node) => {
          const model = node.getModel();
          const { height } = node._cfg.keyShape && node._cfg.keyShape._attrs;
          model.y = middle - height / 2;
        });
        break;

      case 'spaceBetween-vertical':
        spaceBetween(nodes, 'y');
        break;

      case 'spaceBetween-align':
        spaceBetween(nodes, 'x');
        break;

      default:
        break;
    }

    _graph.current.refreshPositions();
  }

  function align(direction) {
    const nodes = _graph.current.findAllByState('node', 'selected');
    // 拿到选中节点的原始x,y的model对象的副本
    const models = nodes.map((node) => {
      return Object.assign({}, node.getModel());
    });
    // 开始对齐
    alignRedo(direction);
    //将对齐和撤销加入undoManager的栈中
    undoManager.add({
      undo: function() {
        nodes.forEach((node) => {
          const model = node.getModel();
          const curNodeModel = models.find((it) => it.id === model.id);
          model.x = curNodeModel.x;
          model.y = curNodeModel.y;
        });
        _graph.current.refreshPositions();
      },
      redo: function() {
        alignRedo(direction);
      },
    });
  }

  function spaceBetween(arr, key) {
    const nodes = sortArr(arr, key);
    const start = nodes[0].getModel()[key];
    const total = getPrevTotalWidth(nodes, nodes.length - 1, key);
    const step = (nodes[nodes.length - 1].getModel()[key] - nodes[0].getModel()[key] - total) / (nodes.length - 1);
    nodes.forEach((node, index) => {
      const model = node.getModel();
      model[key] = start + getPrevTotalWidth(nodes, index, key) + step * index;
    });
  }

  function getPrevTotalWidth(arr, i, key) {
    return arr.reduce((total, it, index) => {
      if (index >= i) {
        return total;
      }
      const { width, height } = it._cfg.keyShape && it._cfg.keyShape._attrs;
      if (key === 'x') {
        total += width;
      }
      if (key === 'y') {
        total += height;
      }
      return total;
    }, 0);
  }

  function sortArr(arr, key) {
    return arr.sort((obj1, obj2) => {
      return obj1.getModel()[key] - obj2.getModel()[key];
    });
  }

  // 撤销
  function undo() {
    if (!hasUndo) {
      return;
    }
    undoManager.undo();
  }

  // 恢复
  function redo() {
    if (!hasRedo) {
      return;
    }
    undoManager.redo();
  }

  function checkUndoManagerState() {
    setHasUndo(undoManager.hasUndo());
    setHasRedo(undoManager.hasRedo());
  }

  return (
    <Row type='flex' gutter={10} justify='start' className='flow-toolbar'>
      <Col className='flow-toolbar-item'>
        <Tooltip title='选择'>
          <IconFontTool
            type={'iconxuanze'}
            className={mode === 'default' ? 'active' : ''}
            onClick={() => (disabled ? setFlowMode('disabled') : setFlowMode('default'))}
          />
        </Tooltip>
      </Col>
      <Col className='flow-toolbar-item'>
        <Tooltip title='拖拽画布'>
          <IconFontTool
            type={'icontuozhuai'}
            className={mode === 'dragCanvas' ? 'active' : ''}
            onClick={() => setFlowMode('dragCanvas')}
          />
        </Tooltip>
      </Col>
      <Col className='flow-toolbar-item'>
        <span className='tool-line' />
      </Col>
      <Col className={!hasUndo ? 'flow-toolbar-item disabled' : 'flow-toolbar-item'}>
        <Tooltip title='撤销'>
          <IconFontTool
            type={'iconchexiao'}
            onClick={() => {
              undo();
            }}
          />
        </Tooltip>
      </Col>
      <Col className={!hasRedo ? 'flow-toolbar-item disabled' : 'flow-toolbar-item'}>
        <Tooltip title='恢复'>
          <IconFontTool type={'iconhuifu'} onClick={() => redo()} />
        </Tooltip>
      </Col>
      <Col className='flow-toolbar-item'>
        <span className='tool-line' />
      </Col>
      <Col className={!isAlignOk ? 'flow-toolbar-item disabled' : 'flow-toolbar-item'}>
        <Tooltip title='垂直置顶'>
          <IconFontTool
            type={'iconchuizhizhiding'}
            onClick={() => {
              align('top');
            }}
          />
        </Tooltip>
      </Col>
      <Col className={!isAlignOk ? 'flow-toolbar-item disabled' : 'flow-toolbar-item'}>
        <Tooltip title='垂直居中'>
          <IconFontTool
            type={'iconchuizhijuzhong'}
            onClick={() => {
              align('middle');
            }}
          />
        </Tooltip>
      </Col>
      <Col className={!isAlignOk ? 'flow-toolbar-item disabled' : 'flow-toolbar-item'}>
        <Tooltip title='垂直置底'>
          <IconFontTool
            type={'iconchuizhizhidibu'}
            onClick={() => {
              align('bottom');
            }}
          />
        </Tooltip>
      </Col>
      <Col className='flow-toolbar-item'>
        <span className='tool-line' />
      </Col>
      <Col className={!isAlignOk ? 'flow-toolbar-item disabled' : 'flow-toolbar-item'}>
        <Tooltip title='水平居左'>
          <IconFontTool
            type={'icon-zuoduiqi'}
            onClick={() => {
              align('left');
            }}
          />
        </Tooltip>
      </Col>
      <Col className={!isAlignOk ? 'flow-toolbar-item disabled' : 'flow-toolbar-item'}>
        <Tooltip title='水平居中'>
          <IconFontTool
            type={'iconshuipingjuzhong'}
            onClick={() => {
              align('center');
            }}
          />
        </Tooltip>
      </Col>
      <Col className={!isAlignOk ? 'flow-toolbar-item disabled' : 'flow-toolbar-item'}>
        <Tooltip title='水平居右'>
          <IconFontTool
            type={'iconshuipingjuyou'}
            onClick={() => {
              align('right');
            }}
          />
        </Tooltip>
      </Col>
      <Col className='flow-toolbar-item'>
        <span className='tool-line' />
      </Col>
      <Col className={!isAlignOk ? 'flow-toolbar-item disabled' : 'flow-toolbar-item'}>
        <Tooltip title='垂直均匀分布'>
          <IconFontTool
            type={'iconchuizhijunyunfenbu'}
            onClick={() => {
              align('spaceBetween-vertical');
            }}
          />
        </Tooltip>
      </Col>
      <Col className={!isAlignOk ? 'flow-toolbar-item disabled' : 'flow-toolbar-item'}>
        <Tooltip title='水平均匀分布'>
          <IconFontTool
            type={'iconshuipingjunyunfenbu'}
            onClick={() => {
              align('spaceBetween-align');
            }}
          />
        </Tooltip>
      </Col>
    </Row>
  );
}
